#include <cmath>
#include <sstream>
#include <fstream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <dirent.h>

#include "compare.h"

using namespace std;

vector<vector<float> > Compare::getdes(const char* filename) {
	float num1;
	string buffer;
	string cmd1;
	vector<float> veclist;
	vector<vector<float> > des_vec;
	ifstream in(filename);
	if (!in) {
		cout<<"cannot open file: "<<filename<<". exit"<<endl;
		exit(1);
	}

	veclist.clear();
	des_vec.clear();
	while (getline(in,buffer)) {
		istringstream is(buffer);
		is >> cmd1;
		if (cmd1 == "#") {
			if (veclist.size() > 1) {
				des_vec.push_back(veclist);
			}
			veclist.clear();
			continue;
		} else {
			stringstream ss(cmd1);
			ss >> num1;
			veclist.push_back(num1);
			continue;
		}
	}
	in.close();
	des_vec.push_back(veclist);
	return des_vec;
}

void Compare::setdes() {
	DIR* pout = NULL;
	struct dirent* pent = NULL;  
	pout = opendir("./out");
	if (pout == NULL){
        cout << "filed to read out/" << endl;
        exit(1);
	}

	data_set.clear();
	fnms.clear();
	while (pent = readdir(pout)) {
		if(pent->d_name[0]!='.') {
			string temnm(pent->d_name);
			fnms.push_back(temnm);
			char filename[64] = "out/";
			strcat(filename,pent->d_name);
			data_set.push_back(getdes(filename));
		} else
			continue;
	}
	closedir(pout);
}

vector<int> Compare::sorting(vector<float> distlist) {
    float temp;
    int temp_index;
    vector<int> indexlist;

    for (int i = 0; i < (int)distlist.size(); i++) {
        indexlist.push_back(i+1);
    }
	for (int i = 0; i < (int)distlist.size();i++) {
		for (int j = 0; j < (int)distlist.size()-i-1; j++) {
			if (distlist[j]>distlist[j+1]) {
				temp = distlist[j];
				distlist[j] = distlist[j+1];
				distlist[j+1] = temp;
                temp_index = indexlist[j];
                indexlist[j] = indexlist[j+1];
                indexlist[j+1] = temp_index;
			}
		}
	}
	return indexlist;
}

string Compare::textKey (const char* key) {
	ifstream in("data/kwlist.txt");
	if (!in) {
		cout<<"Please make sure there is ";
		cout<<"a list file: kwlist.txt"<<endl;
		exit(0);
	}

	string buffer;
	string actualName;
	while (getline(in, buffer)){
		actualName.clear();
		istringstream iss(buffer);
		iss>>actualName;
		if (strcmp(actualName.c_str(), key)==0){
			iss>>actualName;
			return actualName;
		}
	}
	in.close();

	cout<<"The key word \""<<key<<"\" ";
	cout<<"is not in our database"<<endl;
	cout<<"Please directly use the file to search, ";
	cout<<"or bind it in the kwlist.txt"<<endl;

	exit(0);
	return actualName;
}

void Compare::rank(const char* inName) {
	if (data_set.size()<1){
		cout<<"There is no data for ranking"<<endl;
		exit (1);
	}

	string keyname(inName);
	vector<vector<float> > query_key;
	if (keyname.substr(0,3)!="out" && 
		keyname.substr(0,5)!="./out") {
		keyname.clear();
		keyname=textKey(inName);
	}
	query_key=getdes(keyname.c_str());

	float distance=0;
	vector<float> distlist;
    vector<int> rank_result(data_set.size());

	for(int i = 0; i < data_set.size(); i++) {
		distance = dist(query_key, data_set[i]);
		distlist.push_back(distance);
	}
	rank_result = sorting(distlist);
	
	ofstream rout("query_result.txt");
	rout << "Query Key: " << endl;
	rout << "  " << keyname << endl;
	rout << "Query Result:" << endl;
	for(int i = 1; i < (int)rank_result.size(); i++) {
		rout << "  " << i << ": " << fnms[rank_result[i]-1];
		rout << ", L2 dist: " << distlist[rank_result[i]-1] << endl;
	}
	rout.close();
	cout<<"The result was written into query_result.txt"<<endl;
}

float L2dist::dist(vector<vector<float> > des1, vector<vector<float> > des2) {
	float temp=0;
	
	for (int i=0; i<des1.size(); i++){
		for (int j=0; j<des1[0].size(); j++){
			temp += pow((des1[i][j]-des2[i][j]), 2);
		}
	}
	temp=pow(temp, 0.5);

	return temp;
}

